﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using VMS.FTS.APPPUSH.Utils.FontData;

namespace VMS.FTS.APPPUSH.Utils
{
    public class FontUtils
    {
        public static void Dump(string path,ushort fontSize,bool bitmap = false)
        {
            if (fontSize != 7 && fontSize != 10 && fontSize != 12)
            {
                Console.WriteLine("Current don't support font size: " + fontSize);
                return;
            }
            Console.WriteLine("Start loading char map....");
            ElementsMap mapIns = ElementsMap.Instance();
            mapIns.LoadFromFile(path);
            List<JsonCustomElement> Map = mapIns.Map;
            
            Console.WriteLine("Build lookup table....");
            int index = 0;
            List<JsonCustomElement> fontList = new List<JsonCustomElement>();
            byte height = 0;
            foreach (JsonCustomElement kPair in Map)
            {
                if (kPair.Size == fontSize)
                {
                    fontList.Add(kPair);
                    height = kPair.Height;
                }
            }

            // Init header
            FONT_HEADER header;
            if (fontSize == 7)
                header.FontID = 0;
            else if (fontSize == 10)
                header.FontID = 1;
            else
                header.FontID = 0;
            header.FontHeight = height;
            header.CharCount = (byte)fontList.Count;

            // Create lookup table
            FontLookupTable lookupTable = new FontLookupTable();

            Console.WriteLine("Start exporting font....");
            index = 0;
            int offset = 0;
            int baseOffset = Marshal.SizeOf(new FONT_HEADER()) + header.CharCount * Marshal.SizeOf(new LOOKUP_RECORD());

            List<byte[]> fontData = new List<byte[]>();
            offset = baseOffset;
            foreach (JsonCustomElement kPair in fontList)
            {
                Console.Write("\r>>Export element: " + kPair.Name);
                Document doc = new Document(
                    kPair.Width, kPair.Height);

                doc.Elements.Add(new TextLineElement(-1, 0, kPair.Name, 2, (byte)fontSize));

                if (bitmap)
                    FUtils.Instance().ToBitmap(doc).Save("Bitmaps//" + index + ".bmp");
                byte[] buffer = FUtils.Instance().ToBinary(doc);

                lookupTable.Add(new LOOKUP_RECORD((byte)index, (ushort)offset));
                fontData.Add(buffer);
                offset += buffer.Length;
                index++;
            }

            int dataSize = offset - baseOffset;
            // allocate output buffer
            byte[] outBuffer = new byte[offset];
            // header
            outBuffer[0] = header.FontID;
            outBuffer[1] = header.FontHeight;
            outBuffer[2] = header.CharCount;

            // lookuptable
            lookupTable.getBytes().CopyTo(outBuffer, 3);

            // font data
            int tempOffset = baseOffset;
            index = 0;
            foreach (byte[] bytes in fontData)
            {
                bytes.CopyTo(outBuffer, tempOffset);
                tempOffset += bytes.Length;
                index++;
            }
            File.WriteAllBytes(header.FontID + ".font", outBuffer);
            //File.WriteAllText("F7.fonthex", ByteArrayToString(outBuffer, 16));
            Console.WriteLine("\rExporting font finish! File saved at:" + header.FontID + ".font");
        }

        public static string ByteArrayToString(byte[] ba, int wordCount)
        {
            StringBuilder hex = new StringBuilder(ba.Length * 2);
            int i = 0;
            foreach (byte b in ba)
            {
                i++;
                if (i % 16 == 0)
                    hex.AppendFormat("0x{0:x2}, \n ", b);
                else
                    hex.AppendFormat("0x{0:x2}, ", b);

            }
            return hex.ToString();
        }
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct FONT_HEADER
    {
        public byte FontID;
        public byte FontHeight;
        public byte CharCount;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct LOOKUP_RECORD
    {
        public byte Index;
        public ushort Offset;

        public LOOKUP_RECORD(byte index, ushort off)
        {
            Index = index;
            Offset = off;
        }
    }

    class FontLookupTable : List<LOOKUP_RECORD>
    {
        public byte[] getBytes()
        {
            if (Count <= 0) return null;

            // allocate buffer
            byte[] bufer;
            bufer = new byte[Count * Marshal.SizeOf(this[0])];
            int bufOffset = 0;
            foreach (LOOKUP_RECORD record in this)
            {

                byte[] buffer = new byte[3];
                buffer[0] = record.Index;
                BitConverter.GetBytes(record.Offset).CopyTo(buffer, 1);

                buffer.CopyTo(bufer, bufOffset);
                bufOffset += 3;
            }
            return bufer;
        }
    }
}
